package com.wang.example.protocol;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.CharsetUtil;

import java.util.List;

public class HahaDecoder extends ByteToMessageDecoder {
    /**
     * 报文开始的标志 magic是int类型，占4个字节
     * 表示报文长度的 dataLength是int类型，占4个字节
     */
    public final int BASE_LENGTH = 8;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 可读长度必须大于基本长度：报文开始的标志 + 报文长度的字节数
        if (in.readableBytes() >= BASE_LENGTH) {
            // 记录包头开始的index
            int beginReader;
            while (true) {
                //获取读指针readerIndex指向的位置
                beginReader = in.readerIndex();
                // 标记当前readerIndex的位置，可以通过resetReaderIndex方法在回到该位置。
                in.markReaderIndex();
                // 读到协议的开始标志，结束while循环
                if (in.readInt() == Constant.MAGIC) {
                    break;
                }
                //走到这里说明没有找到报文开始标识，前面读取了4个字节，需要复位。
                in.resetReaderIndex();
                in.readByte(); // 每次跳过一个字节后，再去读取包头信息的开始标记
                // 当跳过一个字节后，数据包的长度又变的不满足，此时应该结束，等待后边数据流的到达
                if (in.readableBytes() < BASE_LENGTH) {
                    return;
                }
            }
            // 代码到这里，说明已经读到了报文标识
            // 消息长度
            int length = in.readInt();
            // 判断请求数据包是否到齐
            if (in.readableBytes() < length) { // 数据不齐，回退读指针
                // 还原读指针
                in.readerIndex(beginReader);
                return;
            }
            // 至此，读到一条完整报文
            byte[] data = new byte[length];
            in.readBytes(data);
            out.add(new String(data, CharsetUtil.UTF_8));
        }
    }
}
